package com.ruoyi.web.xxj.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.Threads;
import com.ruoyi.web.xxj.domain.ClassInfo;
import com.ruoyi.web.xxj.domain.ClassOrder;
import com.ruoyi.web.xxj.domain.Product;
import com.ruoyi.web.xxj.domain.ProductOrder;
import com.ruoyi.web.xxj.domain.pojo.PrePayReq;
import com.ruoyi.web.xxj.domain.vo.EachMonthCountObj;
import com.ruoyi.web.xxj.enums.Constants;
import com.ruoyi.web.xxj.enums.PayStatus;
import com.ruoyi.web.xxj.mapper.ProductOrderMapper;
import com.ruoyi.web.xxj.service.IProductOrderService;
import com.ruoyi.web.xxj.util.UniqueOrderNumberGenerator;

import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import com.wechat.pay.java.service.refund.model.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * 文创购买记录Service业务层处理
 *
 * @author ruoyi
 * @date 2024-02-23
 */
@Service
public class ProductOrderServiceImpl implements IProductOrderService {
    private static final Logger log = LoggerFactory.getLogger(ProductOrderServiceImpl.class);

    @Autowired
    private ProductOrderMapper productOrderMapper;
    @Autowired
    private ProductServiceImpl productService;

    /**
     * 查询文创购买记录
     *
     * @param id 文创购买记录主键
     * @return 文创购买记录
     */
    @Override
    public ProductOrder selectProductOrderById(Long id) {
        return productOrderMapper.selectProductOrderById(id);
    }

    /**
     * 查询文创订单
     *
     * @param orderNo 文创订单订单号
     * @return 文创订单
     */
    public ProductOrder selectProductOrderByOrderNo(String orderNo) {
        return productOrderMapper.selectProductOrderByOrderNo(orderNo);
    }

    /**
     * 查询文创购买记录列表
     *
     * @param productOrder 文创购买记录
     * @return 文创购买记录
     */
    @Override
    public List<ProductOrder> selectProductOrderList(ProductOrder productOrder) {
        return productOrderMapper.selectProductOrderList(productOrder);
    }

    /**
     * 新增文创购买记录
     *
     * @param productOrder 文创购买记录
     * @return 结果
     */
    @Override
    public int insertProductOrder(ProductOrder productOrder) {
        productOrder.setCreateTime(DateUtils.getNowDate());
        return productOrderMapper.insertProductOrder(productOrder);
    }

    /**
     * 修改文创购买记录
     *
     * @param productOrder 文创购买记录
     * @return 结果
     */
    @Override
    public int updateProductOrder(ProductOrder productOrder) {
        productOrder.setUpdateTime(DateUtils.getNowDate());
        return productOrderMapper.updateProductOrder(productOrder);
    }

    /**
     * 批量删除文创购买记录
     *
     * @param ids 需要删除的文创购买记录主键
     * @return 结果
     */
    @Override
    public int deleteProductOrderByIds(Long[] ids) {
        return productOrderMapper.deleteProductOrderByIds(ids);
    }

    /**
     * 删除文创购买记录信息
     *
     * @param id 文创购买记录主键
     * @return 结果
     */
    @Override
    public int deleteProductOrderById(Long id) {
        return productOrderMapper.deleteProductOrderById(id);
    }

    @Override
    public int withdraw(Long id) {

        ProductOrder order = this.selectProductOrderById(id);
        this.compareWechatuserId(order.getWechatUserid());
        if (!order.getPayStatus().equals(PayStatus.REFUND_TO_AUDIT.getValue())) {
            log.info("课程订单主键ID[" + id + "]，课程订单状态为[" + PayStatus.getNameByValue(order.getPayStatus()) + "]");
            throw new ServiceException("订单状态为非退款待审核状态，无法撤销订单取消申请！");
        }
        order.setPayStatus(PayStatus.PAIDED.getValue());
        order.setUpdateBy(SecurityUtils.getLoginUser().getWechatUser().getNickname());
        order.setUpdateTime(DateUtils.getNowDate());
        return productOrderMapper.updateProductOrder(order);
    }

    private void compareWechatuserId(Long wechatuserId) {
        if (!SecurityUtils.getLoginUser().getWechatUser().getId().equals(wechatuserId)) {
            log.info("当前用户ID[" + SecurityUtils.getLoginUser().getWechatUser().getId() + "]，订单用户ID[" + wechatuserId + "]");
            throw new ServiceException("订单用户不一致，不允许取消他人订单！");
        }
    }

    /**
     * 取消订单课程
     *
     * @param id
     * @return
     */
    @Override
    public int cancel(Long id, String cancelReason) {

        ProductOrder order = productOrderMapper.selectProductOrderById(id);

        this.compareWechatuserId(order.getWechatUserid());

        log.info("客户ID[" + SecurityUtils.getLoginUser().getWechatUser().getId() +
                "]申请取消文创订单,订单ID[" + id + "],课程ID[" + order.getProductId() + "],文创名称[" + order.getProductName() + "");
      //未支付可直接取消，已支付就得审核
        if (order.getPayStatus().equals(PayStatus.NOPAID.getValue())) {
            order.setPayStatus(PayStatus.CANCEL.getValue());
        } else {
            //生成商户退款订单号
            String outRefundNo = Constants.OrderNo_Prefix.P.name() + System.currentTimeMillis();
            order.setPayStatus(PayStatus.REFUND_TO_AUDIT.getValue());
            order.setRefundNo(outRefundNo);
        }
        order.setCancelReason(cancelReason);
        order.setRemark("取消订单");
        return this.updateProductOrder(order);
    }

    @Override
    public Integer getToYearProductOrderCount() {
        return productOrderMapper.getToYearProductOrderCount();
    }

    @Override
    public List<EachMonthCountObj> getEachMonthProductOrderNum() {
        return productOrderMapper.getEachMonthProductOrderNum();
    }

    public synchronized List<ProductOrder> createOrder(PrePayReq prePayReq, Long weChatUserId) {
        if (CollectionUtils.isEmpty(prePayReq.getProductOrderReqList())) {
            return null;
        }
        checkInventory(prePayReq.getProductOrderReqList());
        List<ProductOrder> orders = new ArrayList<ProductOrder>();
        boolean useAddOnPrice = false;
        if (prePayReq.getProductOrderReqList().size() == 1 && Objects.nonNull(prePayReq.getClassOrderReq())) {
        	useAddOnPrice = true;
		}
        for (PrePayReq.ProductOrderReq req : prePayReq.getProductOrderReqList()) {
        	ProductOrder productOrder = new ProductOrder();
        	BeanUtils.copyProperties(req, productOrder);
            productOrder.setWechatUserid(weChatUserId);
            //保证订单号绝对不重复
            Threads.sleep(1);
            productOrder.setOrderNo(Constants.OrderNo_Prefix.P.name() + System.currentTimeMillis());
            Product product = productService.selectProductById(req.getProductId());
            productOrder.setPayAmount(computePayAmount(useAddOnPrice,req, product));
            productOrder.setPayStatus(PayStatus.NOPAID.getValue());
            productOrder.setCreateTime(DateUtils.getNowDate());
            productOrder.setUpdateTime(DateUtils.getNowDate());
            productOrderMapper.insertProductOrder(productOrder);
            orders.add(productOrder);
		}

        return orders;
    }

    /**
     * 检查库存
     *
     * @param productOrderReq
     */
	private void checkInventory(List<PrePayReq.ProductOrderReq> productOrderReqList) {
    	for (PrePayReq.ProductOrderReq productOrderReq : productOrderReqList) {
    		Product product = productService.selectProductById(productOrderReq.getProductId());
            if (StringUtils.equalsIgnoreCase(product.getUseCalculate(), "Y")) {
                if (product.getInventory() < productOrderReq.getPayNum()) {
                    throw new IllegalArgumentException(product.getProductName()+"库存数量不足");
                }
            }
		}

    }

    private BigDecimal computePayAmount(boolean useAddOnPrice,PrePayReq.ProductOrderReq req, Product product) {
        BigDecimal price;
        //加购订单使用加购价
        if (useAddOnPrice == true) {
            price = product.getAddOnPrice();
        } else {
            price = product.getProductPrice();
        }
        return price.multiply(new BigDecimal(req.getPayNum()));
    }

    public void processOrder(String orderNo, Transaction transaction) {
        ProductOrder productOrder = productOrderMapper.selectProductOrderByOrderNo(orderNo);
        if (StringUtils.equals(productOrder.getPayStatus(), PayStatus.PAIDED.getValue())) {
            log.warn("重复回调 该订单已处理！！！！");
            return;
        }
        productOrder.setPayStatus(PayStatus.PAIDED.getValue());
        productOrder.setUpdateTime(new Date());
        productOrder.setWxpayTradeNo(transaction.getOutTradeNo());
        productOrderMapper.updateProductOrder(productOrder);
        //扣减库存
        Product product = productService.selectProductById(productOrder.getProductId());
        if (StringUtils.equalsIgnoreCase(product.getUseCalculate(), "Y")) {
            product.setSoldCount(product.getSoldCount() + productOrder.getPayNum());
            product.setInventory(product.getInventory() - productOrder.getPayNum());
            product.setUpdateTime(new Date());
            productService.updateProduct(product);
        }
    }

    public void processRefund(String orderNo, RefundNotification refundNotification) {
        ProductOrder productOrder = productOrderMapper.selectProductOrderByOrderNo(orderNo);
        if (StringUtils.equalsIgnoreCase(productOrder.getPayStatus(), PayStatus.REFUNDED.getValue())
                || StringUtils.equalsIgnoreCase(productOrder.getPayStatus(), PayStatus.REFUND_FAIL.getValue())) {
            log.warn("重复回调 该订单已处理！！！！");
            return;
        }
        if (StringUtils.equalsIgnoreCase(refundNotification.getRefundStatus().name(), Status.SUCCESS.name())) {
            productOrder.setPayStatus(PayStatus.REFUNDED.getValue());
        } else if (StringUtils.equalsIgnoreCase(refundNotification.getRefundStatus().name(), Status.ABNORMAL.name())) {
            productOrder.setPayStatus(PayStatus.REFUND_FAIL.getValue());
        }
        productOrder.setRefundNo(refundNotification.getOutRefundNo());
        productOrder.setUpdateTime(new Date());
        productOrderMapper.updateProductOrder(productOrder);
        //退款成功增加库存
        if (StringUtils.equalsIgnoreCase(refundNotification.getRefundStatus().name(), Status.SUCCESS.name())) {
            Product product = productService.selectProductById(productOrder.getProductId());
            if (StringUtils.equalsIgnoreCase(product.getUseCalculate(), "Y")) {
                product.setSoldCount(product.getSoldCount() - productOrder.getPayNum());
                product.setInventory(product.getInventory() + productOrder.getPayNum());
                product.setUpdateTime(new Date());
                productService.updateProduct(product);
            }
        }
    }

}
